package collect

import (
	"context"
	"fmt"
	"github.com/1141520944/go-library/library/log"
	"github.com/hpcloud/tail"
	"os"
	"path/filepath"
	"sync"
	"time"
)

func NewFileTail(log *log.Logger, ctx context.Context) *fileTail {
	c := &fileTail{
		tails:     make([]*tail.Tail, 0, 10),
		indexT:    sync.Map{},
		Create:    make(chan Create),
		IndexInfo: make([]*Index, 0, 10),
		//indexI:    sync.Map{},
		Result:   make(chan *SendLogInfo, 10),
		IndexMsg: make(chan *Index, 10),
		log:      log,
		ctx:      ctx,
	}
	go c.initModifier()
	return c
}

// initModifier 修改器
func (c *fileTail) initModifier() {
	for {
		select {
		case val := <-c.Create:
			var (
				old, now *tail.Tail
				dir      = filepath.Dir(val.Path)
				err      error
				i        int //索引
			)
			v, ok := c.indexT.Load(dir) //查看文件夹下是否有 tail
			c.log.Infow("tail create path", val.Path)
			now, err = c.create(val.Path, val.Offset)
			if err != nil {
				c.log.Errorw("method", "fileTail.initModifier c.create", "err", err.Error())
				continue
			}
			if ok {
				//关闭之前的记录
				old = c.tails[v.(int)]
				if err = old.Stop(); err != nil {
					c.log.Errorw("method", "fileTail.initModifier old.Stop", "err", err.Error())
					//continue
				}
				c.tails[v.(int)] = now
				//读取当前的文件索引
				info, err := c.GetIndexInfo(v.(int))
				if err != nil {
					c.log.Errorw("method", "fileTail.initModifier c.GetIndexInfo", "err", err.Error())
				}
				if info != nil {
					//发送索引文件消息
					c.IndexMsg <- info
				}
				//在原来位置 记录当前文件
				c.IndexInfo[v.(int)] = &Index{
					Name:   val.Path,
					Time:   time.Now().Format(time.DateTime),
					Row:    0,
					Offset: val.Offset,
					Status: NoComplete,
				}
				//记录索引的位置
				i = v.(int)
			} else {
				//创建索引
				c.indexT.Store(val.Path, len(c.tails))
				i = len(c.IndexInfo)
				//记录当前文件索引
				c.IndexInfo = append(c.IndexInfo, &Index{
					Name:   filepath.Base(val.Path),
					Time:   time.Now().Format(time.DateTime),
					Row:    0,
					Offset: val.Offset,
					Status: NoComplete,
				})
				//记录当前ail
				c.tails = append(c.tails, now)
			}
			println(i)
			println(val.Path)
			//启动
			go c.Do(now, val.Path, i)
		}
	}
}
func (c *fileTail) create(path string, offset int64) (t *tail.Tail, err error) {
	if _, err = os.Stat(path); os.IsNotExist(err) {
		return nil, fmt.Errorf("error! %s not found", path)
	}
	config := tail.Config{
		ReOpen:    true,                                      // 重新打开
		Follow:    true,                                      // 是否跟随
		Location:  &tail.SeekInfo{Offset: offset, Whence: 2}, // 从文件的哪个地方开始读
		MustExist: false,                                     // 文件不存在不报错
		Poll:      true,
	}
	tails, err := tail.TailFile(path, config)
	if err != nil {
		return nil, err
	}
	return tails, nil
}
func (c *fileTail) Do(t *tail.Tail, path string, index int) {
	c.log.Infow("tail Do path", path)
	for {
		select {
		case val := <-t.Lines:
			if val.Err != nil {
				break
			}
			c.Result <- FormatLogData(path, val.Text, val.Time)
			//更新索引信息
			c.IndexInfo[index].Row += 1
			c.IndexInfo[index].Offset += int64(len(val.Text)) //todo \n
		}
	}
}
func (c *fileTail) GetIndexInfo(index int) (*Index, error) {
	fileInfo, err := os.Stat(c.IndexInfo[index].Name)
	if err != nil {
		return nil, err
	}
	if fileInfo.Size() > c.IndexInfo[index].Offset {
		c.IndexInfo[index].Status = NoComplete
	} else {
		c.IndexInfo[index].Status = Complete
	}
	return c.IndexInfo[index], nil
}
